home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
ada
/
gwuada_9.zip
/
12C.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-07-27
|
38KB
|
1,285 lines
/*
* Copyright (C) 1985-1992 New York University
*
* This file is part of the Ada/Ed-C system. See the Ada/Ed README file for
* warranty (none) and distribution info and also the GNU General Public
* License for more details.
*/
/* chapter 12, part c */
#include "hdr.h"
#include "vars.h"
#include "attr.h"
#include "dbxp.h"
#include "dclmapp.h"
#include "miscp.h"
#include "smiscp.h"
#include "setp.h"
#include "nodesp.h"
#include "errmsgp.h"
#include "chapp.h"
/* ctype.h needed by desig_to_op */
#include <ctype.h>
static Tuple instantiation_code; /* code from instantiation */
static int instantiation_code_n = 0; /* current length */
static Node instantiate_object(Node, Symbol, Symbolmap);
static int can_rename(Node);
static Tuple flatten_tree(Node);
static int is_discr_ref(Node, Tuple);
static Symbol instantiate_type(Node, Symbol, Symbolmap);
static Symbol valid_type_instance(Symbol, Symbol, Symbolmap);
static Symbol valid_scalar_instance(Symbol, Symbol, Symbolmap);
static void check_actual_constraint(Symbol, Symbol);
static Symbol valid_priv_instance(Symbol, Symbol, Symbolmap);
static Symbol valid_access_instance(Symbol, Symbol, Symbolmap);
static Symbol valid_array_instance(Symbol, Symbol, Symbolmap);
static int is_valid_disc_instance(Symbol, Symbol, Symbolmap);
static Tuple get_array_info(Symbol);
static void generic_subprog_instance(Node, Symbol, Symbolmap, int);
static Tuple find_renamed_types(int, Tuple, Symbol, Node);
static Node make_rename_node(Symbol, Node);
static void instantiation_code_with(Node);
/* number of slots to expand instantiation_code when full, initial alloc*/
#define INSTANTIATION_CODE_INC 50
Tuple instantiate_generics(Tuple gen_list, Node instance_node)
/*;instantiate_generics*/
{
/* Produce the list of renamings which transforms generic parameters
* into actual ones.
* Generic types play a special role in this renaming. We collect the
* Instantiations of generic types into the map -type_map-and use it
* in a substitution procedure to obtain the signature of generic
* subprogram arguments.
* Generic subprograms are also renamed by the actual subprograms, and
* the mapping from one to the other is also added to the same renaming
* map.
*/
Tuple error_instance, empty_tuple, inst_code;
Symbolmap type_map, empty_typemap;
Tuple gtup;
Tuple instance, new_instance;
int i, j, k, gn, ni, seen, same_formal_subprog;
Node assoc;
int first_named, exists, is_default;
Symbol g_name, name, over;
Node actual;
Symbol actual_type;
Node init_node;
Node id_node;
Tuple tup;
int nat;
Fortup ft1;
Forset fs1;
if( cdebug2 > 3) TO_ERRFILE("AT PROC : instantiate_generics ");
/* const error_instance = [ [], {} ]; $$ES7 */
instantiation_code = tup_new(0);
instantiation_code_n = 0;
type_map = symbolmap_new();
empty_tuple = tup_new(0);
empty_typemap = symbolmap_new();
error_instance = tup_new2((char *) empty_tuple, (char *) empty_typemap);
instance = N_LIST(instance_node);
if (tup_size( instance) > tup_size( gen_list)){
errmsg("Too many actuals in generic instantiation", "12.3", instance_node);
}
/* Values may be supplied either positionally or by name. */
exists = FALSE;
FORTUPI(assoc=(Node), instance, i, ft1);
if (N_AST1(assoc) != OPT_NODE){
exists = TRUE;
break;
}
ENDFORTUP(ft1);
if (exists) {
first_named = i;
exists = FALSE;
for (k=i; k <= tup_size(instance); k++) {
if (N_AST1((Node)instance[k]) == OPT_NODE){
exists = TRUE;
break;
}
}
if (exists) {
errmsg("Positional association after named one", "12.3",
(Node)instance[k]);
return error_instance;
}
}
else
first_named = tup_size(instance) + 1;
seen = first_named - 1;
new_instance = tup_new(0);
for (i = 1; i <= seen; i++) {
actual = N_AST2((Node)instance[i]);
new_instance = tup_with(new_instance, (char *) actual);
}
/* Collect named instances in the proper order.*/
gn = tup_size(gen_list);
for (i=first_named; i <= gn; i++) {
gtup = (Tuple) gen_list[i];
g_name = (Symbol) gtup[1];
init_node = (Node) gtup[2];
exists = FALSE;
ni = tup_size(instance);
for (j=first_named; j <= ni; j++) {
id_node = N_AST1((Node) instance[j]);
if (id_node == OPT_NODE) continue;
if (streq(N_VAL(id_node), ORIG_NAME(g_name))) {
exists = TRUE;
break;
}
}
if (exists) {
actual = N_AST2((Node) instance[j]);
new_instance = tup_with(new_instance, (char *) actual);
seen += 1;
if (NATURE(g_name) == na_procedure ||
NATURE(g_name) == na_function) {
name = dcl_get(DECLARED(SCOPE_OF(g_name)), N_VAL(id_node));
/*
* We must distinguish between generic formal
* subprogram and those defined in the generic spec.
* We perform the check only on those defined in the
* generic spec (i.e. those that have their ALIAS
* field defined.
*/
same_formal_subprog = 0;
FORSET(over = (Symbol), OVERLOADS(name), fs1);
if (ALIAS(over)!=(Symbol)0) same_formal_subprog++;
ENDFORSET(fs1);
if (same_formal_subprog > 1)
errmsg("named associations not allowed for overloaded names",
"12.3(3)", id_node);
}
/* Otherwise a default must exist for this generic parameter.*/
/* Mark the place for use below.*/
}
else if (init_node != OPT_NODE )
new_instance = tup_with(new_instance, (char *) OPT_NODE);
else {
errmsg_id("Missing instantiation for generic parameter %" ,
g_name, "12.3", current_node);
return error_instance;
}
}
#ifdef TBSN
if (cdebug2 > 0){
TO_ERRFILE('new instance ' + str new_instance);
}
#endif
/* Now process all actuals in succession. */
gn = tup_size(gen_list);
for (i = 1; i <= gn; i++) {
gtup= (Tuple) gen_list[i];
g_name = (Symbol) gtup[1];
init_node = (Node) gtup[2];
actual = (Node) new_instance[i];
if (actual != OPT_NODE ) {
adasem(actual);
if (NATURE(g_name) == na_in) {
/* type check expression for in parameter. */
actual_type = replace(TYPE_OF(g_name), type_map);
check_type(actual_type, actual);
}
else if (NATURE(g_name)== na_procedure
|| NATURE(g_name)== na_function) {
/* Actual may be given by an operator symbol, which appear */
/* as string literal. */
is_default = FALSE;
if (N_KIND(actual) == as_string_literal)
desig_to_op(actual);
find_old(actual);
}
}
else {
/* Use default value given.*/
actual = init_node;
if (NATURE(g_name) == na_in )
/* May depend on generic types: replace by their instances.*/
actual = instantiate_tree(init_node, type_map);
else { /* generic subprogram parameter */
/* If the box was used to specify a default subprogram, we
* retrieve the visible instances of the generic identifier.
*/
is_default = TRUE;
if (N_KIND(actual) == as_simple_name
&& streq(N_VAL(actual), "box")) {
actual = node_new(as_simple_name);
N_VAL(actual) = original_name(g_name);
copy_span(instance_node, actual);
find_old(actual);
is_default = FALSE;
}
else if (N_KIND(actual) == as_attribute)
/* Will depend on generic types. Must instantiate. */
actual = instantiate_tree(init_node, type_map);
}
}
nat = NATURE(g_name);
if (nat == na_in || nat == na_inout)
/* TBSL: see if instantiation_code might be large in which case
* may want to avoid too many tup_with calls
*/
instantiation_code_with(
instantiate_object(actual, g_name, type_map));
else if (nat == na_procedure || nat == na_function)
generic_subprog_instance(actual, g_name, type_map, is_default);
else { /* generic type. */
actual_type = instantiate_type(actual, g_name, type_map);
if (actual_type == (Symbol)0)
return error_instance;
else {
symbolmap_put(type_map, g_name, actual_type);
if (is_scalar_type(g_name))
/* indicate the instantiation of its base type as well. */
symbolmap_put(type_map, TYPE_OF(g_name),
base_type(actual_type));
}
}
}
if (seen != tup_size(instance)) {
/* Not all name